# encoding:utf-8
'''
@author : xaing
@time : 2019/4/10 14:40
@地址 : 广州
@作用 :
@结果 :
'''



import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QPushButton, QAction, QInputDialog
# 输入对话框
from PyQt5.QtWidgets import QInputDialog
# QLineEdit 是一个允许输入和编辑纯文本的单行控件。系统中的撤销、重做、复制、剪切和粘贴都可用于该控件
from PyQt5.QtWidgets import QLineEdit, QTextEdit
from PyQt5.QtWidgets import QApplication, QGridLayout
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtGui import QPalette, QBrush, QPixmap
import time

from version1.qt import qtUtils as qt
from version1 import common, logUtils as log, checkUtils as check, fileUtils as file, sqlUtils as sql, sshUtils as ssh, dateUtils as date

import test


class sshConnectWin(QMainWindow):


    def __init__(self):
        super().__init__()
        # 调用初始化方法
        self.initUI()



    def initUI(self):
        '''
        初始化窗口
        :return:
        '''

        # //初始化，建表
        self.connect = sql.getConnectSqlite3('./ssh.db')
        if sql.existTable('ssh', self.connect) is False:
            createSql = 'CREATE TABLE ssh(id varchar(36) primary key not null,ip varchar(15),prot varchar(7),userName varchar(45),password varchar(65),uploadFile varchar(600),tomcat varchar(600),bak varchar(600))'
            sql.execute(self.connect, createSql, True)




        # 主窗口
        qt.getMainWindows(self, 600, 400, '自动部署应用小工具v1.0', './2.png', None, 500, 300, False)

        # 字体
        fontWindows = QFont('楷体', 10)
        self.setFont(fontWindows)


        # 背景图
        qt.addBackgroundImg(self, "./4.png")

        # 文本字体
        fontText = QFont('楷体', 10)

        # 文本
        self.text1 = qt.addText(self, 180, 50, "远程主机地址：", "#33CCFF", fontText, 130, 50)
        self.text2 = qt.addText(self, 180, 80, "端口号：", "#33CCFF", fontText, 130, 50)
        self.text3 = qt.addText(self, 180, 110, "用户名：", "#33CCFF", fontText, 130, 50)
        self.text4 = qt.addText(self, 180, 140, "密码：", "#33CCFF", fontText, 130, 50)
        self.text5 = qt.addText(self, 180, 170, "待部署文件夹：", "#33CCFF", fontText, 130, 50)
        self.text6 = qt.addText(self, 180, 200, "猫的文件目录：", "#33CCFF", fontText, 130, 50)
        self.text7 = qt.addText(self, 180, 230, "备份存储目录：", "#33CCFF", fontText, 130, 50)

        # 文本输入框
        self.input1 = qt.addInput(self, 320, 60, None, None)
        self.input2 = qt.addInput(self, 320, 90, None, None)
        self.input3 = qt.addInput(self, 320, 120, None, None)
        self.input4 = qt.addInput(self, 320, 150, None, None)
        self.input5 = qt.addInput(self, 320, 180, None, None)
        self.input6 = qt.addInput(self, 320, 210, None, None)
        self.input7 = qt.addInput(self, 320, 240, None, None)

        self.input5.setEnabled(False)

        fontButton = QFont('楷体', 8)
        # 按钮样式
        buttonStyle = '''
            QPushButton{border:none;color:white;font-size:14px}
            QPushButton{background:#7700BB;}
            QPushButton:hover{border-left:4px solid red;font-weight:700;}
        '''

        buttonStyle2 = '''
                    QPushButton{border:none;color:white;font-size:16px}
                    QPushButton{background:#888800;}
                '''

        buttonStyle3 = '''
                            QPushButton{border:none;color:white;font-size:16px}
                            QPushButton{background:#FF3333;}
                        '''

        buttonStyle4 = '''
                        QPushButton{border:none;color:white;font-size:16px}
                        QPushButton{background:#32CD32;}
                    '''

        buttonStyle5 = '''
                        QPushButton{border:none;color:white;font-size:16px}
                        QPushButton{background:#B8860B;}
                    '''



        # 按钮
        # self.left_button1 = qt.getButton('历史', self, 20, 40, 100, 40, './2.png', None, fontButton, buttonStyle, None)
        self.left_button2 = qt.getButton('日志', self, 20, 100, 100, 40, './2.png', '部署日志', fontButton, buttonStyle, self.tip)
        self.left_button3 = qt.getButton('关于', self, 20, 160, 100, 40, './2.png', None, fontButton, buttonStyle, self.about)

        self.left_button4 = qt.getButton('选择文件夹', self, 465, 180, 100, 20, None, None, fontButton, buttonStyle, self.winOpenFolder)

        self.left_button5 = qt.getButton('启动部署', self, 80, 320, 100, 40, None, '开始部署项目到服务器', fontButton, buttonStyle4, self.batckUpdateTomcatApp)
        self.left_button6 = qt.getButton('连接测试', self, 200, 320, 100, 40, None, '测试SSH连接状态', fontButton, buttonStyle5, self.testConnect)
        self.left_button7 = qt.getButton('保存', self, 320, 320, 100, 40, None, '保存数据到数据库', fontButton, buttonStyle2, self.save)
        self.left_button8 = qt.getButton('重置', self, 440, 320, 100, 40, None, '清除填写数据', fontButton, buttonStyle3, self.reset)

        # 下拉框
        sqlConnectList = self.getAllSsh()
        self.comboBox = qt.addComboBox(self, sqlConnectList, 20, 40, 100, 30, fontButton, self.selectionchange)


        # 显示窗口
        self.show()



    def batckUpdateTomcatApp(self):
        try:
            qt.mouseAround(self)
            self.check(False)
            # 测试连接
            map = self.getInput()
            try:
                connect = ssh.connectSSH(map['ip'], map['user'], map['password'], map['prot'])
                if connect is not None:
                    # qt.addTisPopup(self, None, "连接成功")

                    # 获取到tomcat的pid
                    pidInstructions = "ps -ef | grep tomcat8/ | grep -v grep | awk '{print $2}'"
                    tomcatPid = ssh.exec(connect, pidInstructions)
                    # TODO 判断是否获取到pid
                    if len(tomcatPid) == 0:
                        # qt.errorPopup(self, None, "获取tomcat的 PID 失败，请确认tomcat位置是否正确，不正确则要修改脚本。或tomcat未启动，现在继续执行")
                        pass
                    else:
                        # qt.addTisPopup(self, None, "获取pid成功，PID：" + str(tomcatPid[0]))
                        # 干掉pid
                        kill = "kill -9 " + str(tomcatPid[0])
                        ssh.exec(connect, kill)

                    # 备份
                    # 先创建备份文件夹
                    createFile = map['bak'] + "/" + str(date.getDateyymmddhms())
                    log.outDebugLog("备份文件位置：", createFile)
                    createBckInstructions = common.outStr("mkdir -p ", createFile)
                    log.outDebugLog("执行创建文件命令：", createBckInstructions)
                    ssh.exec(connect, createBckInstructions)
                    # 备份迁移
                    bakML = common.outStr("cp -aruv ", map["tomcat"], " ", createFile)
                    log.outDebugLog("备份命令：", bakML)
                    moveCatalog = ssh.exec(connect, bakML)
                    common.outStr("mkdir -p ", createFile)
                    # TODO 无法判定是否复制成功

                    # 上传覆盖
                    # 创建临时的上传文件区
                    uplpadTemp = map['bak'] + "/" + "uplpadTemp"
                    # 删除临时区
                    ssh.exec(connect, common.outStr("rm -rf ", uplpadTemp))
                    ssh.exec(connect, common.outStr("mkdir -p ", uplpadTemp))
                    log.outDebugLog("临时上传区：", common.outStr("mkdir -p ", uplpadTemp))
                    # 上传
                    common.printStr(uplpadTemp)
                    common.printStr(map["uploadFile"])
                    ssh.uploadFileCatalog(map["ip"], map["prot"], map["user"], map["password"], map["uploadFile"], uplpadTemp)
                    # 覆盖
                    last = file.getLastPath(map["uploadFile"].replace("\\", "/"))
                    cp = "\cp -rf " + uplpadTemp + last + " " + map["tomcat"]
                    log.outDebugLog("执行强制覆盖：", cp)
                    ssh.exec(connect, cp)
                    # 删除临时区
                    ssh.exec(connect, common.outStr("rm -rf ", uplpadTemp))

                    # 启动tomcat
                    index = map["tomcat"].rfind("/webapps")
                    if index == -1:
                        qt.errorPopup(self, None, "未找到tomcat启动目录")
                        return
                    tomcatBase = map["tomcat"][0:index]
                    log.outDebugLog("tomcat基础路径：", tomcatBase)
                    start = "cd " + tomcatBase + "/bin; ./startup.sh"
                    ssh.exec(connect, start)
                    log.outDebugLog("执行启动tomcat:", start)
                    # 校验tomcat是否启动
                    tomcatPid = ssh.exec(connect, pidInstructions)
                    qt.addTisPopup(self, None, "新的PID为：" + str(tomcatPid[0]))
                    # 监控tomcat信息

                else:
                    qt.errorPopup(self, None, "连接失败")

            except Exception as e:
                qt.errorPopup(self, None, e)

        except Exception as e:
            qt.errorPopup(self, None, e)
            return
        finally:
            qt.mouseDefault(self)


    def testConnect(self):
        '''
        测试连接是否成功
        :return:
        '''
        try:
            qt.mouseAround(self)
            self.check(False)
            # 测试连接
            map = self.getInput()
            try:
                conn = ssh.connectSSH(map['ip'], map['user'], map['password'], map['prot'])
                if conn is not None:
                    qt.addTisPopup(self, None, "连接成功")
                else:
                    qt.errorPopup(self, None, "连接失败")

            except Exception as e:
                qt.errorPopup(self, None, e)

        except Exception as e:
            qt.errorPopup(self, None, e)
            return
        finally:
            qt.mouseDefault(self)


    def selectionchange(self, i):
        '''
        下拉框触发的事件
        :param i: 这个 i 是下拉框的下标，从0开始
        :return:
        '''
        ip = self.comboBox.currentText()
        data = sql.execute(self.connect, "select * from ssh where ip = '" + ip + "'", False)
        if not len(data):
            qt.errorPopup(self, None, common.outStr("数据库查询不到:", ip, " 该IP地址，请刷新后重试"))
            return
        # 填充数据
        self.fillData(data[0][1], data[0][2], data[0][3], data[0][4], data[0][5], data[0][6], data[0][7])

    def getAllSsh(self):
        '''
        返回数据库中保存的IP列表
        :return:
        '''
        select = "select * from ssh"
        sshAll = sql.execute(self.connect, select, False)
        log.outDebugLog(sshAll)
        list = ['请选择']
        if len(sshAll) > 0:
            for i in sshAll:
                list.append(i[1])

        return list


    def save(self):
        try:
            insertSQL = self.check(True)
            # 保存到数据库
            sql.execute(self.connect, insertSQL, True)
            qt.addTisPopup(self, None, "保存成功")

            # 下拉框重载
            select = "select * from ssh where ip = '" + str(self.input1.text()) + "'"
            sshAll = sql.execute(self.connect, select, False)
            s = sshAll[0][1]
            self.comboBox.addItem(s)

            self.reset()

        except Exception as e:
            qt.errorPopup(self, None, e)
            return




    def check(self, isSave):
        '''
        检查是否合法,并返回插入语句
        :param isSave: 是否校验保存 true 校验 false 不校验保存
        :return:
        '''
        ip = self.input1.text()
        prot = self.input2.text()
        user = self.input3.text()
        password = self.input4.text()
        uploadFile = self.input5.text()
        tomcat = self.input6.text()
        bak = self.input7.text()

        if common.checkNull(ip):
            raise Exception("IP地址 不能为空")

        if common.checkNull(prot):
            raise Exception("端口 不能为空")

        if common.checkNull(user):
            raise Exception("用户名 不能为空")

        if common.checkNull(password):
            raise Exception("密码 不能为空")

        if common.checkNull(uploadFile):
            raise Exception("上传文件夹路径 不能为空")

        if common.checkNull(tomcat):
            raise Exception("tomcat部署路径 不能为空")

        if common.checkNull(bak):
            raise Exception("备份地址 不能为空")

        if check.isIp(ip) is False:
            raise Exception("不是合法的IP地址")

        if check.isPort(prot) is False:
            raise Exception("不是合法的端口")

        if file.isFileManyCheck(uploadFile) is True:
            raise Exception("上传目录不能是文件")

        if isSave is True:
            exisIp = sql.execute(self.connect, "select * from ssh where ip = '" + ip + "'", False)
            if len(exisIp):
                raise Exception("该IP已经保存过，不能重复保存")

        uploadFile = uploadFile.replace("/", "\\")
        uuid = sql.getUUID()
        instrt = common.outStr("insert into ssh (id, ip, prot, username, password, uploadfile, tomcat, bak) values", "('", uuid, "',", "'", ip, "',", "'", prot, "',", "'", user, "',","'", password, "',","'", uploadFile, "',","'", tomcat, "',","'", bak, "')")
        return instrt

    def winOpenFolder(self):
        '''
        选择文件夹并回显
        :return:
        '''
        file = qt.winOpenFolder(self)
        self.input5.setText(file)

    def tip(self):
        '''
        日志按钮点击提示
        :return:
        '''
        qt.addTisPopup(self, None, "该功能暂未开发，期待你的加入")

    def about(self):
        qt.aboutPopup(self, None, "项目地址：https://gitee.com/sprouting/common")


    def reset(self):
        '''
        重置
        :return:
        '''
        self.getInput()
        self.fillData("", "", "", "", "", "", "")
        log.outDebugLog("执行清理完成")


    def getInput(self):
        '''
        获取input值
        :return:
        '''
        ip = self.input1.text()
        prot = self.input2.text()
        user = self.input3.text()
        password = self.input4.text()
        uploadFile = self.input5.text()
        tomcat = self.input6.text()
        bak = self.input7.text()
        inputMap = {"ip" : ip, "prot" : prot, "user" : user, "password" : password, "uploadFile" : uploadFile, "tomcat" : tomcat, "bak" : bak}
        log.outDebugLog(inputMap)
        return inputMap


    def fillData(self, t1, t2, t3, t4, t5, t6, t7):
        '''
        填充数据到输入框中
        :param t1:
        :param t2:
        :param t3:
        :param t4:
        :param t5:
        :param t6:
        :param t7:
        :return:
        '''
        self.input1.setText(str(t1))
        self.input2.setText(str(t2))
        self.input3.setText(str(t3))
        self.input4.setText(str(t4))
        self.input5.setText(str(t5))
        self.input6.setText(str(t6))
        self.input7.setText(str(t7))







if __name__ == '__main__':
    app = QApplication(sys.argv)

    ex = sshConnectWin()

    sys.exit(app.exec_())

